Indice


Progetto scelto: 5


Presentazione problema

In questo report, ci siamo concentrati sull’elaborazione di un modello lineare predittivo per determinare il numero di vittorie in funzione dei rimbalzi annuali effettuati dalle squadre nella NBA. Il modello si applica esclusivamente a squadre che hanno disputato almeno 82 partite per stagione, considerando un arco temporale che va dal 1976 al 2011.

L’approccio del modello lineare si basa sull’adozione di coefficienti accuratamente selezionati, mirati a massimizzare la significatività e l’aderenza alla nostra interpretazione dell’impatto di specifiche variabili sulle vittorie. Questi coefficienti sono stati scelti in modo da riflettere al meglio la nostra concezione di quali fattori influenzino maggiormente il successo delle squadre.

Ulteriori informazioni riguardanti l’esecuzione del programma e l’utilizzo della funzione predittiva sono fornite nei paragrafi successivi, dove viene anche descritto il processo di sviluppo e validazione del modello.


Analisi dati iniziale e grafici

Il chunk riportato legge un dataset da un file, filtra le righe in base ai criteri sopra riportati, calcola una nuova variabile e offre la possibilità di ottenere un riassunto statistico dei dati filtrati.

filepath <- here("0_Materiale", "basketball_teams.txt")
dataset <- read.delim(filepath)
# str(dataset)

FIRST <- 1976 # primo anno del range da considerare per lo studio
LAST <- 2011 # ultimo anno del range da considerare per lo studio 

df <- dataset [dataset$lgID=="NBA" & dataset$year >= FIRST & dataset$year <= LAST & dataset$games==82,]
df$reb <- df$o_reb + df$d_reb

# summary(df)

Correlazione dati

Analisi rimbalzi

Nel nostro dataframe sono incluse variabili specifiche per analizzare in dettaglio il ruolo dei rimbalzi nel basket. Ecco una descrizione degli acronimi utilizzati:

  • o_oreb: Rimbalzi ottenuti in attacco
    • Questo valore rappresenta il numero di volte in cui una squadra recupera la palla dopo un tiro mancato mentre è in fase offensiva. È un indicatore diretto dell’aggressività e dell’efficacia offensiva di una squadra.
  • o_dreb: Rimbalzi subiti in attacco
    • Indica il numero di rimbalzi che una squadra concede all’avversario mentre è in attacco. Un valore più basso suggerisce una maggiore capacità di mantenere il controllo della palla dopo un tiro mancato.
  • o_reb: Totale rimbalzi in attacco
    • Questa è la somma dei rimbalzi ottenuti e subiti in attacco. Fornisce una misura complessiva dell’attività di rimbalzo di una squadra quando è in fase offensiva.
  • d_oreb: Rimbalzi subiti in difesa
    • Rappresenta il numero di rimbalzi che una squadra permette all’avversario di ottenere mentre è in difesa. Minimizzare questo numero è cruciale per prevenire seconde opportunità di punteggio per l’avversario.
  • d_dreb: Rimbalzi ottenuti in difesa
    • Indica il numero di volte in cui una squadra recupera la palla dopo un tiro mancato dall’avversario mentre è in difesa. È un indicatore chiave dell’efficacia difensiva e della capacità di interrompere l’attacco avversario.
  • d_reb: Totale rimbalzi in difesa
    • Questo è il totale dei rimbalzi che una squadra ottiene o concede mentre è in difesa. Offre una visione olistica dell’impegno e dell’efficacia di una squadra nel controllare la zona difensiva durante il gioco.

Percentuale di valori non zero per ciascuna variabile di interesse

## [1] "Percentage non-zero o_oreb:  100"
## [1] "Percentage non-zero o_dreb:  100"
## [1] "Percentage non-zero o_reb:  100"
## [1] "Percentage non-zero d_oreb:  100"
## [1] "Percentage non-zero d_dreb:  100"
## [1] "Percentage non-zero d_reb:  100"

Analisi vittorie

Test

Test Anderson-Darling sui rimbalzi

Il test Anderson-Darling è un test statistico non parametrico, utilizzato per verificare l’ipotesi che un campione di dati provenga da una particolare distribuzione, in questo caso, la distribuzione normale. È particolarmente sensibile alle deviazioni nella coda della distribuzione.
- Range: 0 a \(+\infty\)
- Interpretazione: Valori più bassi indicano una maggiore aderenza alla distribuzione normale. Si confronta il valore di test con valori critici specifici per determinare se rifiutare l’ipotesi di normalità.

ad.test(df$reb)
## 
##  Anderson-Darling normality test
## 
## data:  df$reb
## A = 3.6997, p-value = 3.1e-09

Con un livello di significatività (\(\alpha\)) di 0.01 e un p-value molto piccolo (3.1e-09) ottenuto dal test di normalità di Anderson-Darling per i dati della variabile df$reb, puoi concludere che hai sufficiente evidenza statistica per respingere lipotesi nulla che i dati seguono una distribuzione normale.Con il tuo livello di significatività del 0.01 e il p-value molto piccolo (3.1e-09), il p-value è inferiore al livello di significatività, quindi respingeresti lipotesi nulla. Questo suggerisce che i dati nella variabile df$reb non seguono una distribuzione normale al livello di significatività del 0.01. In termini più pratici, hai abbastanza evidenza statistica per concludere che la variabile df$reb non segue una distribuzione normale basandoti sui risultati del test di Anderson-Darling.

Test Kolmogorov-Smirnov

Il test Kolmogorov-Smirnov (K-S) è un metodo non parametrico utilizzato per determinare se un campione di dati segue una specifica distribuzione, in questo caso, la distribuzione normale. È ampiamente impiegato per la sua generalità e la facilità di implementazione.
- Range: 0 a 1
- Interpretazione: Valori più bassi indicano una maggiore somiglianza alla distribuzione normale. Un valore di test significativamente grande porta al rifiuto dell’ipotesi di normalità.

ks.test(df$reb, "pnorm")
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  df$reb
## D = 1, p-value < 2.2e-16
## alternative hypothesis: two-sided

Il risultato che hai ottenuto riguarda il test di Kolmogorov-Smirnov a campione singolo sui dati contenuti nella variabile df$reb. Il test KS confronta la distribuzione empirica dei tuoi dati con una distribuzione teorica (spesso una distribuzione uniforme). In breve, il risultato suggerisce che i tuoi dati non seguono la distribuzione teorica presunta, e cè un elevata probabilità che la differenza osservata sia statisticamente significativa.

Test Shapiro-Wilk

Il test Shapiro-Wilk è un metodo statistico non parametrico utilizzato specificatamente per testare la normalità di un campione di dati. È noto per la sua affidabilità e precisione, soprattutto in campioni di dimensioni ridotte.
- Range: 0 a 1
- Interpretazione: Valori più vicini a 1 suggeriscono una maggiore aderenza alla distribuzione normale. Valori significativamente bassi indicano la deviazione dalla normalità.

ks.test(df$reb, "pnorm")
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  df$reb
## D = 1, p-value < 2.2e-16
## alternative hypothesis: two-sided

In sintesi, il risultato del test di Shapiro-Francia indica che i tuoi dati nella variabile df$reb non seguono una distribuzione normale. Questo è supportato dal valore basso del p-value, il quale suggerisce che la differenza tra la distribuzione dei tuoi dati e una distribuzione normale è statisticamente significativa.


Presentazione modello lineare

Modello: L’importanza dei rimbalzi

Abbiamo creato un modello lineare per esplorare come i rimbalzi influenzano le vittorie in NBA. L’idea è semplice: capire se squadre che rimbalzano meglio vincono di più. Il modello analizza diversi tipi di rimbalzi (offensivi, difensivi) e come questi si traducono in successo sul campo.

Formule

Le formule che usiamo si concentrano su diversi aspetti dei rimbalzi, come recuperare la palla dopo un tiro sbagliato o proteggere il canestro. Ogni formula ci dà un’idea di come le squadre gestiscono e sfruttano i rimbalzi durante le partite. L’obiettivo è vedere quale impatto hanno questi fattori sulle vittorie.

\(\text{Formula1} = \frac{\text{Rimbalzi offensivi in attacco}}{\text{Tiri sbagliati su azione}}\)

  • Formula 1: Efficienza nel Rimbalzo Offensivo
    Questa formula calcola la percentuale di rimbalzi offensivi catturati dalla squadra in seguito ai tiri mancati. Il numeratore, “Rimbalzi offensivi in attacco”, rappresenta il totale dei rimbalzi catturati dopo un tiro mancato dall’attacco. Il denominatore, “Tiri sbagliati su azione”, è il numero totale di tiri non riusciti dalla squadra. Il quoziente fornisce un indice diretto della competenza di una squadra nel mantenere il possesso della palla dopo un tentativo di tiro fallito, un aspetto cruciale per generare opportunità di punteggio aggiuntive.

\(\text{Formula2} = \frac{\text{Rimbalzi difensivi in difesa presi}}{\text{Tiri sbagliati su azione degli avversari}}\)

  • Formula 2: Competenza nel Rimbalzo Difensivo Questa formula misura l’efficacia della squadra nel recuperare i rimbalzi difensivi. Il numeratore, “Rimbalzi difensivi in difesa presi”, indica il totale dei rimbalzi catturati dalla squadra in difesa. Il denominatore, “Tiri sbagliati su azione degli avversari”, è il numero di tiri falliti dalla squadra avversaria. Il risultato fornisce un’indicazione quantitativa della capacità di una squadra di terminare l’attacco avversario e iniziare una transizione offensiva, elemento fondamentale per il controllo del flusso di gioco.

\(\text{Formula3} = \frac{\text{Palle riprese in attacco} + 1.5 \times \text{Palle riprese in difesa}}{\text{Palle perse in attacco} + 2 \times \text{Rimbalzi subiti in difesa}}\)

  • Formula 3: Bilancio Rimbalzi/Palle Perse Questa formula presenta un rapporto complesso, dove il numeratore somma “Palle riprese in attacco” (rimbalzi offensivi) e “Palle riprese in difesa” (rimbalzi difensivi) moltiplicate per 1.5, un fattore che sottolinea l’importanza dei rimbalzi difensivi. Il denominatore combina “Palle perse in attacco” e “Rimbalzi subiti in difesa” moltiplicati per 2, indicando le occasioni perse di recupero di rimbalzi. Questa formula è progettata per valutare la gestione globale dei rimbalzi da parte di una squadra, enfatizzando il valore della difesa rispetto all’attacco.

\(\text{Formula4} = (\text{Palle riprese in attacco - Palle perse in attacco}) + 1.5*(\text{Palle riprese in difesa - Palle perse in difesa})\)

  • Formula 4: Efficienza Rimbalzi Netta Questa formula calcola la differenza netta tra i rimbalzi catturati e quelli persi, sia in attacco che in difesa, applicando un coefficiente di 1.5 ai rimbalzi difensivi. Il calcolo evidenzia il saldo netto di rimbalzi catturati contro quelli persi, con un’enfasi aggiuntiva sulla componente difensiva. Questo indice fornisce una misura diretta dell’efficacia complessiva di una squadra nel dominare il gioco sui rimbalzi.

\(\text{Formula5} = \frac{(\frac{\text{Rimbalzi subiti in difesa}}{\text{Palle perse in difesa}})}{(\frac{\text{Rimbalzi subiti in attacco}}{\text{Palle perse in attacco}})}\)

  • Formula 5: Rapporto Rimbalzi/Palle Perse Questa formula offre un confronto tra l’effetto dei rimbalzi sulla perdita di palla in attacco e in difesa. Il numeratore rappresenta il rapporto tra “Rimbalzi subiti in difesa” e “Palle perse in difesa”, mentre il denominatore fa lo stesso per l’attacco. Questo rapporto mette in luce l’impatto dei rimbalzi sulle opportunità perse, sia in termini di difesa che di attacco.

\(\text{Formula6} = (\text{Rimbalzi ottenuti in attacco} + \text{Rimbalzi ottenuti in difesa}) - (\text{Rimbalzi subiti in difesa} - \text{Rimbalzi subiti in attacco})^2\)

  • Formula 6: Bilancio Complessivo Rimbalzi
    Questa formula calcola un indice che tiene conto sia dei rimbalzi ottenuti in attacco (Rimbalzi ottenuti in attacco) e in difesa (Rimbalzi ottenuti in difesa), sia dei rimbalzi subiti in difesa (Rimbalzi subiti in difesa) e in attacco (Rimbalzi subiti in attacco), elevando al quadrato la differenza tra i rimbalzi subiti. Offre una visione complessiva dell’efficacia della squadra nel controllo dei rimbalzi sotto entrambi i canestri.

\(\text{Formula7} = (\text{Efficienza nel Rimbalzo Offensivo} + \text{Competenza nel Rimbalzo Difensivo})^2\)

  • Formula 7: Sinergia Tra Rimbalzi Offensivi e Difensivi
    Combina le misurazioni dell’efficienza nei rimbalzi offensivi (Efficienza nel Rimbalzo Offensivo) e difensivi (Competenza nel Rimbalzo Difensivo), elevandone la somma al quadrato. Questo calcolo evidenzia l’importanza della sinergia tra le due componenti del gioco sui rimbalzi.

\(\text{Formula8} = \frac{\text{Rimbalzi ottenuti in attacco}}{\text{Totale rimbalzi in attacco}}\)

  • Formula 8: Proporzione Rimbalzi Offensivi
    Questa formula determina la percentuale dei rimbalzi offensivi (Rimbalzi ottenuti in attacco) sul totale dei rimbalzi in attacco (Totale rimbalzi in attacco). Fornisce un’indicazione diretta dell’efficienza di una squadra nel recuperare la palla dopo i tiri falliti in attacco.

\(\text{Formula9} = \left(\frac{\text{Rimbalzi ottenuti in attacco}}{\text{Rimbalzi subiti in attacco}}\right)^2\)

  • Formula 9: Predominanza dei Rimbalzi Offensivi
    Calcola il rapporto tra i rimbalzi offensivi ottenuti (Rimbalzi ottenuti in attacco) e i rimbalzi subiti in attacco (Rimbalzi subiti in attacco), elevato al quadrato. Questa formula enfatizza la capacità di una squadra di dominare sotto il proprio canestro in fase offensiva.

\(\text{Formula10} = \left(\frac{\text{Rimbalzi ottenuti in difesa}}{\text{Rimbalzi subiti in difesa}}\right)^2\)

  • Formula 10: Predominanza dei Rimbalzi Difensivi
    Analoga alla Formula 9, ma applicata al contesto difensivo. Misura il rapporto tra i rimbalzi difensivi ottenuti (Rimbalzi ottenuti in difesa) e i rimbalzi subiti in difesa (Rimbalzi subiti in difesa), elevato al quadrato. Sottolinea l’efficacia di una squadra nel proteggere il proprio canestro in fase difensiva.

Modello lineare sul dataframe train

Legenda significato acronimi:

  • o_oreb: Rimbalzi ottenuti in attacco
  • o_dreb: Rimbalzi subiti in attacco
  • o_reb: Totale rimbalzi in attacco
  • d_oreb: Rimbalzi subiti in difesa
  • d_dreb: Rimbalzi ottenuti in difesa
  • d_reb: Totale rimbalzi in difesa
df$f1 <- (df$o_oreb)/(df$o_fga-df$o_fgm)
df$f2 <- (df$d_dreb)/(df$d_fga-df$d_fgm)
df$f3 <- (df$o_oreb + 1.5 * df$d_dreb)/(df$o_dreb + 2 * df$d_oreb)
df$f4 <- (df$o_oreb - df$o_dreb) + 1.5 * (df$d_dreb - df$d_oreb)
df$f5 <- (df$d_oreb / df$d_to) / (df$o_dreb / df$o_to)
df$f6 <- (df$o_oreb + df$d_dreb) - (df$d_oreb - df$o_dreb)^2
df$f7 <- (df$f1 + df$f2)^2
df$f8 <- (df$o_oreb)/(df$o_reb)
df$f9 <- ((df$o_oreb)/(df$o_dreb))^2
df$f10 <- ((df$d_dreb)/(df$d_oreb))^2
num_rows_to_sample <- round(0.7 * nrow(df))
sample_indices <- sample(seq_len(nrow(df)), size = num_rows_to_sample, replace = FALSE)

df = subset(df, select = c("f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "won"))

train <- df[sample_indices, ]
test <- df[-sample_indices, ]

linMod <- lm(won ~ f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 + f10, data = train)
summary (linMod)
## 
## Call:
## lm(formula = won ~ f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 + 
##     f10, data = train)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -11.2420  -3.2706   0.0232   3.2553  13.7690 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  1.146e+03  8.848e+01  12.952  < 2e-16 ***
## f1          -7.788e+02  1.499e+02  -5.194 2.85e-07 ***
## f2          -1.233e+03  1.593e+02  -7.741 4.44e-14 ***
## f3          -4.388e+02  3.406e+01 -12.883  < 2e-16 ***
## f4           8.432e-02  7.897e-03  10.677  < 2e-16 ***
## f5          -1.857e+02  4.761e+00 -39.016  < 2e-16 ***
## f6           1.493e-05  1.503e-06   9.935  < 2e-16 ***
## f7           5.515e+02  7.922e+01   6.962 9.14e-12 ***
## f8          -3.037e+02  7.409e+01  -4.099 4.75e-05 ***
## f9           2.382e+01  2.202e+01   1.082     0.28    
## f10          5.705e+00  8.767e-01   6.507 1.66e-10 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 4.643 on 578 degrees of freedom
## Multiple R-squared:   0.86,  Adjusted R-squared:  0.8576 
## F-statistic: 355.2 on 10 and 578 DF,  p-value: < 2.2e-16

Grafici

TODO: Aggiungere presentazione grafici


Modello lineare normalizzato sul dataframe train

La normalizzazione dei dati è una pratica fondamentale nell’elaborazione di modelli statistici, specialmente nei modelli lineari. Questo processo è volto a standardizzare la scala delle variabili, rendendo più agevole il confronto tra di esse e migliorando l’efficienza dell’algoritmo di regressione. In particolare, la normalizzazione è cruciale quando le variabili hanno scale molto diverse, poiché ciò potrebbe influenzare negativamente la precisione del modello.

Nel codice R seguente, abbiamo normalizzato le variabili del nostro dataframe ‘df’, utilizzando la funzione scale. Questo assicura che ciascuna variabile contribuisca in modo equo al modello, permettendo una più accurata interpretazione dei coefficienti della regressione lineare.

# Normalizziamo le covariate
train$f1_z <- scale(train$f1)
train$f2_z <- scale(train$f2)
train$f3_z <- scale(train$f3)
train$f4_z <- scale(train$f4)
train$f5_z <- scale(train$f5)
train$f6_z <- scale(train$f6)
train$f7_z <- scale(train$f7)
train$f8_z <- scale(train$f8)
train$f9_z <- scale(train$f9)
train$f10_z <- scale(train$f10)

# Normalizzo i dati di test
test$f1_z <- scale(test$f1)
test$f2_z <- scale(test$f2)
test$f3_z <- scale(test$f3)
test$f4_z <- scale(test$f4)
test$f5_z <- scale(test$f5)
test$f6_z <- scale(test$f6)
test$f7_z <- scale(test$f7)
test$f8_z <- scale(test$f8)
test$f9_z <- scale(test$f9)
test$f10_z <- scale(test$f10)

linModNormalized <- lm(won ~ f1_z + f2_z + f3_z + f4_z + f5_z + f6_z + f7_z + f8_z + f9_z + f10_z, data = train)
summary(linModNormalized)
## 
## Call:
## lm(formula = won ~ f1_z + f2_z + f3_z + f4_z + f5_z + f6_z + 
##     f7_z + f8_z + f9_z + f10_z, data = train)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -11.2420  -3.2706   0.0232   3.2553  13.7690 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  40.9847     0.1913 214.217  < 2e-16 ***
## f1_z        -25.1929     4.8502  -5.194 2.85e-07 ***
## f2_z        -59.6783     7.7097  -7.741 4.44e-14 ***
## f3_z        -28.7876     2.2346 -12.883  < 2e-16 ***
## f4_z         22.8296     2.1382  10.677  < 2e-16 ***
## f5_z        -13.0837     0.3353 -39.016  < 2e-16 ***
## f6_z          7.9909     0.8043   9.935  < 2e-16 ***
## f7_z         45.6546     6.5577   6.962 9.14e-12 ***
## f8_z        -10.0106     2.4424  -4.099 4.75e-05 ***
## f9_z          1.4998     1.3863   1.082     0.28    
## f10_z         8.6746     1.3330   6.507 1.66e-10 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 4.643 on 578 degrees of freedom
## Multiple R-squared:   0.86,  Adjusted R-squared:  0.8576 
## F-statistic: 355.2 on 10 and 578 DF,  p-value: < 2.2e-16

Grafici


Test modello lineare

Il processo di test di un modello lineare è cruciale per assicurare la sua affidabilità e accuratezza. Questa fase prevede la valutazione di vari aspetti del modello, come l’adattamento dei dati, la normalità dei residui, l’omoschedasticità e la multicollinearità. Ognuno di questi test fornisce un’indicazione su come il modello si adatta ai dati e su eventuali problemi che potrebbero influenzarne le prestazioni.

Summary

Per una comprensione immediata del modello, è utile visualizzare il riepilogo tramite summary(linModNormalized). Questo fornisce dettagli sui coefficienti, la significatività statistica e altre metriche chiave.

summary (linModNormalized)
## 
## Call:
## lm(formula = won ~ f1_z + f2_z + f3_z + f4_z + f5_z + f6_z + 
##     f7_z + f8_z + f9_z + f10_z, data = train)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -11.2420  -3.2706   0.0232   3.2553  13.7690 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  40.9847     0.1913 214.217  < 2e-16 ***
## f1_z        -25.1929     4.8502  -5.194 2.85e-07 ***
## f2_z        -59.6783     7.7097  -7.741 4.44e-14 ***
## f3_z        -28.7876     2.2346 -12.883  < 2e-16 ***
## f4_z         22.8296     2.1382  10.677  < 2e-16 ***
## f5_z        -13.0837     0.3353 -39.016  < 2e-16 ***
## f6_z          7.9909     0.8043   9.935  < 2e-16 ***
## f7_z         45.6546     6.5577   6.962 9.14e-12 ***
## f8_z        -10.0106     2.4424  -4.099 4.75e-05 ***
## f9_z          1.4998     1.3863   1.082     0.28    
## f10_z         8.6746     1.3330   6.507 1.66e-10 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 4.643 on 578 degrees of freedom
## Multiple R-squared:   0.86,  Adjusted R-squared:  0.8576 
## F-statistic: 355.2 on 10 and 578 DF,  p-value: < 2.2e-16

R-quadrato

Il test R-quadrato misura la proporzione della varianza totale della variabile dipendente che viene spiegata dal modello di regressione. Un R-quadrato elevato indica che una grande parte della varianza nella variabile dipendente può essere spiegata dalle variabili indipendenti nel modello.
- Range: 0 a 1
- Interpretazione: 0 indica nessuna spiegazione della varianza da parte del modello. 1 indica una spiegazione completa della varianza da parte del modello.

summary_linModNormalized <- summary(linModNormalized)
r_squared <- summary_linModNormalized$r.squared
cat("R-squared:", r_squared, "\n")
## R-squared: 0.8600321

R-quadrato Adattato

Il R-quadrato adattato modifica il R-quadrato per tenere conto del numero di predittori nel modello. È più affidabile per i modelli con molteplici variabili indipendenti, poiché penalizza la complessità aggiuntiva, fornendo una misura più realistica della bontà di adattamento.
- Range: Può essere negativo, ma generalmente 0 a 1
- Interpretazione: Valori più vicini a 1 indicano una migliore spiegazione della varianza, considerando il numero di predittori.

n <- length(train$o_reb)
k <- length(linModNormalized$coefficients) - 1
adjusted_r_squared <- 1 - ((1 - r_squared) * (n - 1) / (n - k - 1))
cat("R-quadro adattato:", adjusted_r_squared, "\n")
## R-quadro adattato: 0.9872756

Test Shapiro

Il test di Shapiro-Wilk sui residui è utilizzato per valutare la normalità dei residui in un modello di regressione lineare. La normalità dei residui è un’assunzione critica in molti test statistici. Se i residui non seguono una distribuzione normale, le inferenze sulle stime dei parametri potrebbero essere invalide.
- Range: 0 a 1
- Interpretazione: Valori più vicini a 1 suggeriscono una maggiore probabilità che i residui seguano una distribuzione normale.

shapiro.test(residuals(linModNormalized))
## 
##  Shapiro-Wilk normality test
## 
## data:  residuals(linModNormalized)
## W = 0.99601, p-value = 0.1424

Test di omoschedasticità

Il Breusch-Pagan test verifica l’assunzione di omoschedasticità (varianza costante) dei residui in un modello di regressione. La presenza di eteroschedasticità (varianza non costante) nei residui può portare a stime inefficaci e test statistici non affidabili.
- Range: 0 a \(+\infty\)
- Interpretazione: Valori più alti indicano una maggiore probabilità di eteroschedasticità. Si confronta il valore del test con un valore critico (ad es., da una distribuzione chi-quadrato) per determinare la significatività.

bptest(linModNormalized)
## 
##  studentized Breusch-Pagan test
## 
## data:  linModNormalized
## BP = 19.725, df = 10, p-value = 0.03197

Test di multicollinearità

Il test di multicollinearità verifica se esiste una correlazione elevata tra le variabili indipendenti in un modello di regressione lineare. La multicollinearità può causare problemi nella stima dei coefficienti del modello, rendendo difficili l’interpretazione e la significatività statistica delle variabili indipendenti. Strumenti comuni per rilevarla includono il fattore di inflazione della varianza (VIF) e l’indice di tolleranza.
- Range del VIF: 1 a \(+\infty\)
- Interpretazione: 1 indica assenza di multicollinearità. Valori superiori a 5 o 10 sono spesso considerati indicatori di multicollinearità significativa.

car::vif(linModNormalized)
##        f1_z        f2_z        f3_z        f4_z        f5_z        f6_z 
##  641.580712 1621.073174  136.182427  124.683566    3.066859   17.643675 
##        f7_z        f8_z        f9_z       f10_z 
## 1172.802047  162.687917   52.414699   48.463437

Rimozione outliers e LASSO

Questa sezione si dedica all’identificazione e rimozione degli outliers nel nostro modello lineare normalizzato. Gli outliers possono influenzare notevolmente l’accuratezza e l’affidabilità delle previsioni del modello.

Identificazione degli Outliers

Il primo passo è identificare gli outliers. Utilizziamo un grafico di influenza per visualizzare i punti che hanno un impatto maggiore sul modello.

influencePlot(linModNormalized,5)

Successivamente, calcoliamo i residui del modello e identifichiamo come outliers quei punti la cui distanza dalla media è superiore a un valore soglia, in questo caso due deviazioni standard.

residui <- residuals(linModNormalized)

soglia_outlier <- 2 
outliers <- which(abs(residui) > soglia_outlier*sd(residui))

outliers
##  963  936  799 1196  822  900  914 1107  940  624  454 1276 1205  957  891 1128 
##   75   85  104  113  148  179  192  197  203  217  224  231  233  300  313  337 
##  945 1301 1306  837  929 1022  638  470 1224 1026 
##  399  401  428  475  482  483  495  509  515  530

Rimozione degli Outliers

Dopo aver identificato gli outliers, procediamo con la loro rimozione dal dataset di allenamento.

if(length(outliers) != 0)
{
  train_1 <- train[-outliers,]
}else
{
  # questo è il caso in cui non sono presenti outliers
  train_1 <- train
}

Confronto dei Modelli Prima e Dopo la Rimozione degli Outliers

Confrontiamo i summary del modello prima e dopo la rimozione degli outliers per valutare l’impatto di questa operazione sulle prestazioni del modello.

  • Prima della Rimozione degli Outliers:
    Visualizziamo il riepilogo del modello originale per avere un punto di riferimento.
## 
## Call:
## lm(formula = won ~ f1_z + f2_z + f3_z + f4_z + f5_z + f6_z + 
##     f7_z + f8_z + f9_z + f10_z, data = train)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -11.2420  -3.2706   0.0232   3.2553  13.7690 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  40.9847     0.1913 214.217  < 2e-16 ***
## f1_z        -25.1929     4.8502  -5.194 2.85e-07 ***
## f2_z        -59.6783     7.7097  -7.741 4.44e-14 ***
## f3_z        -28.7876     2.2346 -12.883  < 2e-16 ***
## f4_z         22.8296     2.1382  10.677  < 2e-16 ***
## f5_z        -13.0837     0.3353 -39.016  < 2e-16 ***
## f6_z          7.9909     0.8043   9.935  < 2e-16 ***
## f7_z         45.6546     6.5577   6.962 9.14e-12 ***
## f8_z        -10.0106     2.4424  -4.099 4.75e-05 ***
## f9_z          1.4998     1.3863   1.082     0.28    
## f10_z         8.6746     1.3330   6.507 1.66e-10 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 4.643 on 578 degrees of freedom
## Multiple R-squared:   0.86,  Adjusted R-squared:  0.8576 
## F-statistic: 355.2 on 10 and 578 DF,  p-value: < 2.2e-16
  • Dopo la Rimozione degli Outliers:
    Riepiloghiamo il modello aggiornato e visualizziamo un grafico di influenza per osservare l’impatto della rimozione degli outliers.
## 
## Call:
## lm(formula = won ~ f1_z + f2_z + f3_z + f4_z + f5_z + f6_z + 
##     f7_z + f8_z + f9_z + f10_z, data = train_1)
## 
## Residuals:
##    Min     1Q Median     3Q    Max 
## -9.040 -3.039  0.181  2.971  9.569 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  40.8756     0.1749 233.696  < 2e-16 ***
## f1_z        -21.1049     4.7884  -4.407 1.26e-05 ***
## f2_z        -55.4556     7.6078  -7.289 1.08e-12 ***
## f3_z        -31.5742     2.0772 -15.200  < 2e-16 ***
## f4_z         25.8735     2.0180  12.822  < 2e-16 ***
## f5_z        -13.0633     0.3067 -42.590  < 2e-16 ***
## f6_z          8.4989     0.7413  11.465  < 2e-16 ***
## f7_z         41.3564     6.5231   6.340 4.78e-10 ***
## f8_z        -11.5294     2.2141  -5.207 2.71e-07 ***
## f9_z          1.8964     1.2651   1.499    0.134    
## f10_z         9.6483     1.2188   7.916 1.35e-14 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 4.145 on 552 degrees of freedom
## Multiple R-squared:  0.886,  Adjusted R-squared:  0.8839 
## F-statistic: 428.9 on 10 and 552 DF,  p-value: < 2.2e-16

E il rispettivo grafico di influenza

# Crea il grafico di influenza
influence_plot <- influencePlot(linModNormalized_1, id = 5, main = "Influence Plot")
## Warning in applyDefaults(id, defaults = list(method = "noteworthy", n = 2, :
## unnamed id arguments, will be ignored

influence_plot

Conclusione

Entrambi i modelli mostrano prestazioni simili, spiegando circa l’84% della varianza nella variabile dipendente “won”. Tuttavia, la rimozione degli outliers ha leggermente migliorato i risultati. Dato che la differenza tra i due modelli è minima (<0.5%), e quindi trascurabile, abbiamo optato per mantenere il modello che include gli outliers.

LASSO

Visualizzazione Residui e Leverage

Questo blocco di codice utilizza la funzione ols_plot_resid_lev per visualizzare la relazione tra i residui e il leverage per entrambi i modelli lineari (prima e dopo la rimozione degli outliers). Questa visualizzazione aiuta a identificare ulteriori punti influenti o pattern nei residui che potrebbero influenzare le prestazioni del modello.

Utilizzo LASSO

1. Preparazione del Modello di Regressione LASSO

Qui prepariamo un modello di regressione LASSO. Il LASSO è utilizzato per la selezione di variabili e la regolarizzazione, aiutando a prevenire l’overfitting e migliorare la generalizzazione del modello.

  • Definiamo prima la variabile risposta e la matrice dei predittori.
  • Eseguiamo poi la cross-validation k-fold per trovare il valore ottimale di lambda, il parametro di regolarizzazione in LASSO.
  • Visualizziamo il plot di MSE (Mean Squared Error) rispetto ai vari valori di lambda.
# METODO DI REGRESSIONE LASSO

# define response variable
y <- train_1$won

# define matrix of predictor variables
x <- data.matrix(train_1[, c("f1_z", "f2_z", "f3_z", "f4_z", "f5_z", "f6_z", "f7_z", "f8_z", "f9_z", "f10_z")])

# perform k-fold cross-validation to find optimal lambda value
cv_model <- cv.glmnet(x, y, alpha = 1)

# find optimal lambda value that minimizes test MSE
best_lambda <- cv_model$lambda.min
best_lambda
## [1] 0.005611288

  • Addestramento del modello LASSO con il miglior lambda trovato e visualizzazione dei coefficienti.
# Fitting the model with the best lambda
best_model <- glmnet(x, y, alpha = 1, lambda = best_lambda)

# Output coefficients and summary
coef(best_model)
## 11 x 1 sparse Matrix of class "dgCMatrix"
##                        s0
## (Intercept)  4.084481e+01
## f1_z        -2.258061e-04
## f2_z        -2.021537e+01
## f3_z        -2.703804e+01
## f4_z         2.062695e+01
## f5_z        -1.298214e+01
## f6_z         6.850845e+00
## f7_z         1.134240e+01
## f8_z        -1.167319e+01
## f9_z         3.900147e+00
## f10_z        7.096433e+00

2. Previsione con LASSO e Modello Lineare

Effettuiamo le previsioni utilizzando sia il modello LASSO che quello lineare sui dati di test.

# PREDICT

# Lasso Prediction
new = data.matrix(test[,c("f1_z","f2_z","f3_z","f4_z","f5_z", "f6_z", "f7_z", "f8_z", "f9_z", "f10_z")])
prevLasso = predict(best_model, s = best_lambda, newx = new)

# Linear Model Prediction
new = subset(test, select = c("f1_z","f2_z","f3_z","f4_z","f5_z", "f6_z", "f7_z", "f8_z", "f9_z", "f10_z"))
prevLM = predict(linModNormalized_1, newdata = test)

3. Valutazione delle Prestazioni del Modello

Confrontiamo le prestazioni di entrambi i modelli (LASSO e lineare) attraverso diverse metriche.

  • Calcolo del RMS (Root Mean Square)
    Questi blocchi di codice calcolano il RMS, una misura dell’errore di previsione, per il modello LASSO e il modello lineare (LM). Il RMS fornisce una stima dell’errore quadratico medio tra i valori previsti e i valori reali.
# RMS Lasso
sqrt(mean((test$won - prevLasso)^2))
## [1] 4.610133
# RMS LM
sqrt(mean((test$won - prevLM)^2))
## [1] 5.015277
  • Previsioni Binarie e Matrice di Confusione
    Convertiamo le previsioni del modello LASSO in valori binari (0 o 1) e generiamo una matrice di confusione per confrontare le previsioni con i valori reali. Questo passaggio è utile per valutare la classificazione effettuata dal modello.
# Previsioni binarie
prev <- ifelse(prevLasso > 0.5, "1", "0")
prev <- as.factor(as.vector(prev))

# Confusion Matrix: previsioni vs valore reale
table(prev, test$won)
##     
## prev 14 15 16 17 18 19 20 21 22 24 25 26 28 29 30 31 32 33 34 35 36 37 38 39 40
##    1  2  2  1  7  1  5  3  7  5  6  2  4  4  1  2  8  2  5  3  6  7  4  9  3  8
##     
## prev 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
##    1 14 13  6 10  4  6  7  4  6 11  5  4  5  9  7  4 10  4  5  1  3  2  1  1  1
##     
## prev 66 67
##    1  1  1

Calcolo delle Metriche di Valutazione

Calcoliamo diverse metriche di valutazione come l’accuratezza (accuracy), la precisione (precision), la sensibilità (sensitivity), l’F-score e la specificità (specificity). Queste metriche forniscono una valutazione complessiva dell’efficacia del modello.

Ecco come interpretarle:

  • Accuracy (Accuratezza):
    • Significato: La proporzione di previsioni corrette (sia positive che negative) rispetto al totale delle previsioni.
    • Interpretazione: Un valore elevato indica che il modello è generalmente accurato nel classificare sia le istanze positive che quelle negative. Tuttavia, in contesti con classi sbilanciate, una alta accuracy può essere fuorviante.
  • Precision (Precisione):
    • Significato: La proporzione di previsioni positive corrette rispetto al totale delle previsioni positive fatte dal modello.
    • Interpretazione: Misura la qualità delle previsioni positive del modello. Una alta precisione indica che una grande percentuale delle previsioni positive del modello è effettivamente corretta.
  • Sensitivity (Sensibilità) o Recall:
    • Significato: La proporzione di veri positivi rispetto al totale delle istanze effettivamente positive.
    • Interpretazione: Indica quanto bene il modello è in grado di identificare le istanze positive. Un valore alto significa che il modello cattura bene la maggior parte delle istanze positive.
  • F-score:
    • Significato: Una media armonica di precision e sensitivity.
    • Interpretazione: Combina la precisione e la sensibilità in un singolo numero. È utile quando si desidera un equilibrio tra precisione e sensibilità, specialmente in contesti con distribuzioni di classe disuguali.
  • Specificity (Specificità):
    • Significato: La proporzione di veri negativi rispetto al totale delle istanze effettivamente negative.
    • Interpretazione: Misura quanto bene il modello è in grado di identificare le istanze negative. Una alta specificità indica che il modello è efficace nel riconoscere le istanze non positive.
cm <- table(prev, test$won)

# Metriche di Valutazione
accuracy <- sum(cm[1], cm[4]) / sum(cm[1:4])
precision <- cm[4] / sum(cm[4], cm[2])
sensitivity <- cm[4] / sum(cm[4], cm[3])
fscore <- (2 * (sensitivity * precision)) / (sensitivity + precision)
specificity <- cm[1] / sum(cm[1], cm[2])
## [1] "Accuratezza: 0.750000"
## [1] "Precisione: 0.777778"
## [1] "Sensibilità: 0.875000"
## [1] "F-score: 0.823529"
## [1] "Specificità: 0.500000"

Conclusioni